import rclpy
from rclpy.node import Node
from autopatrol_interfaces.srv import SpeachText
import subprocess

class Speaker(Node):
    def __init__(self, node_name):
        super().__init__(node_name)
        self.speech_service = self.create_service(
            SpeachText, 'speech_text', self.speak_text_callback)
        
        # 推荐用 plughw:0,0（旧声卡兼容性更强）
        self.audio_device = 'plughw:0,0'

        # 启动时彻底禁用 PulseAudio
        self.disable_pulseaudio()

    def disable_pulseaudio(self):
        """彻底禁用 PulseAudio 服务和 socket，避免占用设备"""
        try:
            # 停止并禁用服务和 socket
            subprocess.run(['systemctl', '--user', 'stop', 'pulseaudio', 'pulseaudio.socket'], capture_output=True)
            subprocess.run(['systemctl', '--user', 'mask', 'pulseaudio', 'pulseaudio.socket'], capture_output=True)
            # 杀死残留进程
            subprocess.run(['pkill', '-f', 'pulseaudio'], capture_output=True)
            self.get_logger().info("已彻底禁用 PulseAudio，无音频设备占用")
        except Exception as e:
            self.get_logger().warning(f"禁用 PulseAudio 警告：{str(e)}")

    def speak_text_callback(self, request, response):
        text = request.text
        self.get_logger().info(f'正在用 cmn 童声朗读：{text}')
        
        try:
            # espeak-ng 生成 cmn 童音音频（参数不变）
            espeak_cmd = [
                'espeak-ng', '-v', 'cmn+f4',
                '-p', '83', '-s', '155', '-a', '82',  # 童音：音调83、语速155、音量82
                '--stdout', text
            ]
            
            # 修正 aplay 命令：去掉 -S 50000，保留核心兼容参数
            aplay_cmd = [
                'aplay', '-D', self.audio_device,
                '-f', 'S16_LE', '-r', '22050',  # 适配旧声卡格式
                '-B', '100000'                   # 缓冲区大小，解决驱动 bug（关键）
            ]
            
            # 管道执行播放
            espeak_proc = subprocess.Popen(espeak_cmd, stdout=subprocess.PIPE)
            aplay_proc = subprocess.Popen(aplay_cmd, stdin=espeak_proc.stdout)
            aplay_proc.wait()  # 等待播放完成
            
            response.result = True
        except Exception as e:
            self.get_logger().error(f'播放失败：{str(e)}')
            response.result = False
        
        return response

def main():
    rclpy.init()
    node = Speaker('speaker')
    rclpy.spin(node)
    rclpy.shutdown()